package com.wuster.service.impl;



import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wuster.constant.MessageConstant;
import com.wuster.entity.dto.ClockDTO;
import com.wuster.entity.dto.FreeUpdateDTO;
import com.wuster.entity.dto.PageDTO;
import com.wuster.entity.dto.ReportDTO;
import com.wuster.entity.po.Daka;
import com.wuster.entity.po.StudentFreeTime;
import com.wuster.entity.po.TeacherFreeTime;
import com.wuster.entity.po.WeekReport;
import com.wuster.entity.vo.DakaVO;
import com.wuster.entity.vo.FreeTimesVO;
import com.wuster.entity.vo.ReportVO;
import com.wuster.exception.InsertFailedException;
import com.wuster.mapper.*;
import com.wuster.mapper.TeacherFreeMapper;
import com.wuster.result.PageResult;
import com.wuster.service.StudentService;
import com.wuster.utils.BaseContext;

import com.wuster.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Date;

import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
@Slf4j
public class StudentServiceImpl implements StudentService {

    @Autowired
    private DakaMapper dakaMapper;
    @Autowired
    private WeekReportMapper weekReportMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StudentFreeMapper studentFreeMapper;
    @Autowired
    private TeacherFreeMapper teacherFreeMapper;


    // TODO: 是否要对clockDTO中属性值的格式进行规范？
    /**
     * 学生打卡
     * @param clockDTO
     */
    public void toClock(ClockDTO clockDTO) {
        //获得当前的时间
        LocalDate currentLocalDate = LocalDate.now();
        Date currentDate = java.sql.Date.valueOf(currentLocalDate);

        Daka daka = new Daka();
        BeanUtils.copyProperties(clockDTO, daka);
        daka.setUid(BaseContext.getCurrentId());
        daka.setDakaDate(currentDate.toString());

        log.info("当前用户uid：{}", BaseContext.getCurrentId());
        log.info("开始打卡：：：：{}", daka);

        //将数据插入数据库
       try {
           dakaMapper.insert(daka);
        } catch (Exception e){
            log.info("插入打卡记录失败");
        }
    }


    /**
     * 学生个人打卡记录 -分页
     * @param pageDTO
     * @return
     */
    public PageResult selectPage(PageDTO pageDTO) {
        //获取当前的用户id
        Long currentId = BaseContext.getCurrentId();
        //定义查询
        QueryWrapper<Daka> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("uid", currentId)
                .orderByDesc("daka_date")
                .select("id", "daka_date", "end_time", "start_time", "work_time");
        //分页查询
        Page<Daka> page = new Page<>(pageDTO.getPageId(), pageDTO.getPageSize());
        page = dakaMapper.selectPage(page, queryWrapper);

        log.info("测试========{}========{}==========={}=============={}",page.getTotal(), page.getPages(), page.getCurrent(), page.getRecords());

        //对查询到的List<Daka>进行遍历，转换为List<DakaVO>
        List<Daka> dakaList = page.getRecords();
        List<DakaVO> dakaVOList = new ArrayList<>();

        //日期格式化
//        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        for (Daka daka : dakaList){
            DakaVO dakaVO = new DakaVO();

            //设置打卡编号和日期
            dakaVO.setId(daka.getId());
            dakaVO.setDakaDate(daka.getDakaDate());
            //获取打卡时段
            dakaVO.setPeriod(daka.getStartTime() + "-" + daka.getEndTime());
            //获取有效时长
            dakaVO.setWorkTime(daka.getWorkTime());

            dakaVOList.add(dakaVO);
        }

        PageResult pageResult = new PageResult(page.getTotal(), dakaVOList);

        return pageResult;
    }


    /**
     * 学生新增周报
     * @param reportDTO
     * @return
     */
    public void addReport(ReportDTO reportDTO) {
        //获取当前的用户id
        Long currentId = BaseContext.getCurrentId();

        //根据id查询当前用户姓名
        String name = getNameById(currentId);

        //对象属性值复制
        WeekReport weekReport = new WeekReport();
        BeanUtils.copyProperties(reportDTO, weekReport);
        weekReport.setUid(currentId);
        weekReport.setName(name);

        //插入到数据库
        try {
            weekReportMapper.insert(weekReport);
        } catch (Exception e){
            throw new InsertFailedException(MessageConstant.INSERT_REPORT_FAILED);
        }

    }


    /**
     * 个人周报查询
     * @param startDate
     * @param endDate
     * @return
     */
    public PageResult getReport(Date startDate, Date endDate, Integer pageId, Integer pageSize) {
        //获取当前的用户id
        Long currentId = BaseContext.getCurrentId();
        // 分页查询page对象初始化
        Page<WeekReport> page = new Page<>(pageId, pageSize);
        QueryWrapper<WeekReport> wrapper = new QueryWrapper<>();

        //日期不为空，查询构造器加条件
        if (startDate != null)
            wrapper.ge("start_date", startDate);
        if (endDate != null)
            wrapper.le("end_date", endDate);

        wrapper.eq("uid", currentId);
        wrapper.select("id", "start_date", "end_date", "content", "delay", "sentiment", "next_plan");

        //查询
        page = weekReportMapper.selectPage(page, wrapper);

        //将从数据库中查询到的对象转化为VO，返回给前端
        List<WeekReport> weekList = page.getRecords();
        List<ReportVO> reportVOList = new ArrayList<>();
          //处理日期范围字段
        for (WeekReport weekReport : weekList){
            ReportVO reportVO = new ReportVO();
            BeanUtils.copyProperties(weekReport, reportVO);
            reportVO.setPeriod(weekReport.getStartDate() + "~" + weekReport.getEndDate());
            reportVOList.add(reportVO);
        }

        return new PageResult(page.getTotal(), reportVOList);
    }



    /**
     * 学生--空闲时间段查询
     * @param weekId
     * @return
     */
    public List<FreeTimesVO> getfree(Integer weekId) {
        //创建freeList，用于存储五天的FreeTimesVO
        List<FreeTimesVO> freeList = new ArrayList<>();
        Long uid = BaseContext.getCurrentId();

        //根据weekId判断，查询的是本周还是下周
        if (weekId == 0 || weekId == 1){
            //获取周一到周五每天的日期
            Date[] dateList = CommonUtils.getDateByWeekId(weekId);

            for (int i = 0; i < 5; i++) {
                log.info("学生空闲时间段查询：{}" ,dateList[i]);
                // 根据 uid和日期查询学生每一天的空闲状态
                StudentFreeTime studentFree = getStudentFree(uid, dateList[i].toString());

                // 如果查询为空，则将 studentFree 初始化，防止空指针异常
                if (studentFree == null)
                    studentFree = new StudentFreeTime();

                // 创建VO对象，并将PO对象转换为VO对象
                // 1.设置每个时间段的空闲
                FreeTimesVO freeTimesVO = new FreeTimesVO(studentFree.getOne(), studentFree.getTwo(),
                        studentFree.getThree(), studentFree.getFour(), studentFree.getFive(),
                        studentFree.getSix(), studentFree.getSeven(), studentFree.getEight(), studentFree.getNine());
                // 2.设置空闲的日期
                freeTimesVO.setDateTime(dateList[i].toString());
                //3.设置索引（前端需要）
                freeTimesVO.setIndex(i+1);
                //4.设置weekId
                freeTimesVO.setWeekId(weekId);

                freeList.add(freeTimesVO);
            }
        }
        else
            log.info("weekId错误！ {}", weekId);

        return freeList;
    }




    /**
     * 学生修改or插入空闲时间段
     * @param freeUpdateDTOList
     * @return
     */
    public void setFreeTime(FreeUpdateDTO[] freeUpdateDTOList) {
        //获得当前用户的uid
        Long currentId = BaseContext.getCurrentId();

        // 将前端传过来的进行遍历
        for (FreeUpdateDTO freeUpdateDTO : freeUpdateDTOList) {
            Date todayDate = freeUpdateDTO.getDateTime();
            StudentFreeTime oldFree = new StudentFreeTime();

            //更新or插入 学生空闲表
            // 1. 根据uid和日期 判断表中是否存在该条记录
            StudentFreeTime studentFreePO = getStudentFree(currentId, todayDate.toString());
            if (studentFreePO == null){
                //2.不存在则插入
                //属性拷贝
                studentFreePO = new StudentFreeTime();
                BeanUtils.copyProperties(freeUpdateDTO, studentFreePO);
                studentFreePO.setDayDate(freeUpdateDTO.getDateTime());
                studentFreePO.setUid(currentId);

                studentFreeMapper.insert(studentFreePO);
            } else {
                // 更新studentFreePO前复制一个备份，用作教师空闲表更新操作
                BeanUtils.copyProperties(studentFreePO, oldFree);

                //3.存在则更新
                BeanUtils.copyProperties(freeUpdateDTO, studentFreePO);
                studentFreeMapper.updateById(studentFreePO);
            }

            // TODO 同步更新教师空闲表
            //同步更新or插入 教师空闲表
            // 1. 根据日期 判断教师空闲表中是否有该条记录
            TeacherFreeTime teacherFreePO = getTeacherFree(todayDate);
            if (teacherFreePO == null){
                // 2. 没有则说明这个日期的数据 表中还没有，  插入新数据
                teacherFreePO = new TeacherFreeTime();
                BeanUtils.copyProperties(freeUpdateDTO, teacherFreePO);     //对象属性拷贝
                teacherFreePO.setDayDate(freeUpdateDTO.getDateTime());
                teacherFreeMapper.insert(teacherFreePO);
            } else {
                // 3. 有则更新表（获取该条数据，转成po对象，与DTO中表示九个空闲字段的属性值相加，转成一个新的po对象，将该po对象更新到数据库中）     teacherFreePO - oldFree + freeUpdateDTO
                // 更新空闲字段
                teacherFreePO.setFreePeople(
                        teacherFreePO.getOne() - oldFree.getOne() + freeUpdateDTO.getOne(),
                        teacherFreePO.getTwo() - oldFree.getTwo() + freeUpdateDTO.getTwo(),
                        teacherFreePO.getThree() - oldFree.getThree() + freeUpdateDTO.getThree(),
                        teacherFreePO.getFour() - oldFree.getFour() + freeUpdateDTO.getFour(),
                        teacherFreePO.getFive() - oldFree.getFive() + freeUpdateDTO.getFive(),
                        teacherFreePO.getSix() - oldFree.getSix() + freeUpdateDTO.getSix(),
                        teacherFreePO.getSeven() - oldFree.getSeven() + freeUpdateDTO.getSeven(),
                        teacherFreePO.getEight() - oldFree.getEight() + freeUpdateDTO.getEight(),
                        teacherFreePO.getNine() - oldFree.getNine() + freeUpdateDTO.getNine()
                );

                teacherFreeMapper.updateById(teacherFreePO);
            }
        }
    }








    //-------------------提取的部分------------------------------------------------------------

    /**
     * 根据日期来查询 teacher_free 的数据
     * @param todayDate  当天的日期
     * @return
     */
    private TeacherFreeTime getTeacherFree(Date todayDate) {
        //QueryWrapper来进行条件的添加
        LambdaQueryWrapper<TeacherFreeTime> wrapper = new LambdaQueryWrapper();
        // 查看数据库中是否存在该条记录， 构造查询条件
        wrapper.eq(TeacherFreeTime::getDayDate, todayDate).select();

        return teacherFreeMapper.selectOne(wrapper);
    }



    /**
     * 根据学生uid和date来查询 student_free里的记录
     * @return
     */
    public StudentFreeTime getStudentFree(Long uid, String dayDate){
        //QueryWrapper来进行条件的添加
        LambdaQueryWrapper<StudentFreeTime> wrapper = new LambdaQueryWrapper();
        // 查看数据库中是否存在该条记录， 构造查询条件
        wrapper.eq(StudentFreeTime::getUid, uid)
                .eq(StudentFreeTime::getDayDate, dayDate)
                .select();

        StudentFreeTime studentFreeTime = studentFreeMapper.selectOne(wrapper);

        //查询该条数据
        return studentFreeTime;
    }




    /**
     * 根据uid查询姓名
     * @param uid
     * @return
     */
    private String getNameById(Long uid){
        return userMapper.selectById(uid).getUserName();
    }


}
